// Decompiled by Jad v1.5.8e2. Copyright 2001 Pavel Kouznetsov.
// Jad home page: http://kpdus.tripod.com/jad.html
// Decompiler options: packimports(3) fieldsfirst ansi space 
// Source File Name:   IsoValue.java

package com.solab.iso8583;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.Date;

// Referenced classes of package com.solab.iso8583:
//			IsoType

public class IsoValue
	implements Cloneable
{

	private IsoType type;
	private int length;
	private Object value;

	public IsoValue(IsoType t, Object value)
	{
		if (t.needsLength())
			throw new IllegalArgumentException("Fixed-value types must use constructor that specifies length");
		type = t;
		this.value = value;
		if (type == IsoType.LLVAR || type == IsoType.LLLVAR)
		{
			length = value.toString().length();
			if (t == IsoType.LLVAR && length > 99)
				throw new IllegalArgumentException("LLVAR can only hold values up to 99 chars");
			if (t == IsoType.LLLVAR && length > 999)
				throw new IllegalArgumentException("LLLVAR can only hold values up to 999 chars");
		} else
		{
			length = type.getLength();
		}
	}

	public IsoValue(IsoType t, Object val, int len)
	{
		type = t;
		value = val;
		length = len;
		if (length == 0 && t.needsLength())
			throw new IllegalArgumentException("Length must be greater than zero");
		if (t == IsoType.LLVAR || t == IsoType.LLLVAR || t == IsoType.LLLVARCN)
		{
			if (length == 0)
				length = val.toString().length();
			if (t == IsoType.LLVAR && length > 99)
				throw new IllegalArgumentException("LLVAR can only hold values up to 99 chars");
			if (t == IsoType.LLLVAR && length > 999)
				throw new IllegalArgumentException("LLLVAR can only hold values up to 999 chars");
			if (t == IsoType.LLLVARCN && length > 999)
				throw new IllegalArgumentException("LLLVAR can only hold values up to 999 chars");
		}
	}

	public IsoType getType()
	{
		return type;
	}

	public int getLength()
	{
		return length;
	}

	public Object getValue()
	{
		return value;
	}

	public String toString()
	{
		if (value == null)
			return "ISOValue<null>";
		if (type == IsoType.NUMERIC || type == IsoType.AMOUNT)
		{
			if (type == IsoType.AMOUNT)
				return type.format((BigDecimal)value, 12);
			if (value instanceof Number)
				return type.format(((Number)value).longValue(), length);
			else
				return type.format(value.toString(), length);
		}
		if (type == IsoType.ALPHA)
			return type.format(value.toString(), length);
		if (type == IsoType.LLLVAR || type == IsoType.LLLVAR)
			return value.toString();
		if (value instanceof Date)
			return type.format((Date)value);
		else
			return value.toString();
	}

	public Object clone()
	{
		try {
		      return super.clone(); } catch (CloneNotSupportedException ex) {
		    }
		    return null;
	}

	public boolean equals(Object other)
	{
		if (other == null || !(other instanceof IsoValue))
			return false;
		IsoValue comp = (IsoValue)other;
		return comp.getType() == getType() && comp.getValue().equals(getValue()) && comp.getLength() == getLength();
	}

	public void write(OutputStream outs, boolean binary)
		throws IOException
	{
		if (type == IsoType.LLLVAR || type == IsoType.LLVAR || type == IsoType.LLLVARCN)
		{
			if (binary)
			{
				if (type == IsoType.LLLVAR)
					outs.write(length / 100);
				outs.write((length % 100) / 10 << 4 | length % 10);
			} else
			{
				if (type == IsoType.LLLVAR)
					outs.write(length / 100 + 48);
				if (type == IsoType.LLLVARCN)
					outs.write(length / 100 + 48);
				if (length >= 10)
					outs.write((length % 100) / 10 + 48);
				else
					outs.write(48);
				outs.write(length % 10 + 48);
			}
		} else
		if (binary)
		{
			byte buf[] = (byte[])null;
			if (type == IsoType.NUMERIC)
				buf = new byte[length / 2 + length % 2];
			else
			if (type == IsoType.AMOUNT)
				buf = new byte[6];
			else
			if (type == IsoType.DATE10 || type == IsoType.DATE4 || type == IsoType.DATE_EXP || type == IsoType.TIME)
				buf = new byte[length / 2];
			if (buf != null)
			{
				toBcd(toString(), buf);
				outs.write(buf);
				return;
			}
		}
		if (value instanceof byte[])
			outs.write((byte[])value);
		else
			outs.write(toString().getBytes());
	}

	private void toBcd(String value, byte buf[])
	{
		int charpos = 0;
		int bufpos = 0;
		if (value.length() % 2 == 1)
		{
			buf[0] = (byte)(value.charAt(0) - 48);
			charpos = 1;
			bufpos = 1;
		}
		while (charpos < value.length()) 
		{
			buf[bufpos] = (byte)(value.charAt(charpos) - 48 << 4 | value.charAt(charpos + 1) - 48);
			charpos += 2;
			bufpos++;
		}
	}
}
